package com.wzw.springboot.principle.mvc.advice;

import com.wzw.springboot.principle.mvc.annotation.UnifiedController;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 对JSON数据格式传输方式添加自定义的拦截
 * <p>
 * WebMvcConfigurationSupport.requestMappingHandlerAdapter()
 * RequestMappingHandlerAdapter.initControllerAdviceCache()
 * ControllerAdviceBean.findAnnotatedBeans()
 * ControllerAdvice controllerAdvice = beanFactory.findAnnotationOnBean(name, ControllerAdvice.class);
 * OrderComparator.sort(adviceBeans);
 *
 * @author Wangzhiwen
 */
@RestControllerAdvice
@SuppressWarnings("all")
public class UnifiedResponseBodyAdvice implements ResponseBodyAdvice<Object>, Ordered {
    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }

    /**
     * 是否拦截该返回值
     *
     * @param returnType    返回值类型
     * @param converterType 转换器类型
     * @return true 支持 false 不支持，不支持时不执行下述方法
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), UnifiedController.class);
    }

    /**
     * 返回值前置拦截
     *
     * @param body                  the body to be written
     * @param returnType            the return type of the controller method
     * @param selectedContentType   the content type selected through content negotiation
     * @param selectedConverterType the converter type selected to write to the response
     * @param request               the current request
     * @param response              the current response
     * @return the body that was passed in or a modified (possibly new) instance
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        return body;
    }
}
